﻿/* Template done by
 * 
 * Richard Clark
 * Project Hoshimi Lead Manager
 * Contact at ori@c2i.fr
 * 
*/
using System;
using System.Collections.Generic;
using System.Text;

using System.Drawing;
using VG.Common;
using VG.Map;

namespace Los_Borbotones
{
    #region Collector

    [Characteristics(ContainerCapacity = 15, CollectTransfertSpeed = 5, Scan = 5, MaxDamage = 5, DefenseDistance = 5, Constitution = 15)]
    public class Collector : VG.Common.NanoCollector, IActionable
    {

        public enum CollectorWhatToDoNextAction
        {
            NothingToDo,
            MoveToHoshimi,
            CollectAZN,
            AutoDestroy,
            TransferToNeedle,
            MoveToAZN
        }

        public const int SquadNumber = 0;
        public int m_turns_of_recollection = 4;
        private CollectorWhatToDoNextAction m_WhatToDoNext = CollectorWhatToDoNextAction.NothingToDo;

        public Point HP_point;
        public Group my_group = null;

        #region IAction Members


        // Acciones del collector.
        public void DoActions()
        {
            if(this.State == NanoBotState.WaitingOrders)
                CollectActions();
            else if (this.State == NanoBotState.Moving)
            {
                CheckDefendActions();
            }
        }

        private void CheckDefendActions()
        {
            foreach (NanoBotInfo bot in this.PlayerOwner.OtherNanoBotsInfo)
            {
                if (bot.PlayerID == 0)
                {
                    if (Utils.MDistance(this.Location, bot.Location) <= this.DefenseDistance + 3)
                    {
                        this.StopMoving();
                        this.DefendTo(bot.Location, 4);
                        if (m_WhatToDoNext == CollectorWhatToDoNextAction.CollectAZN)
                            this.m_WhatToDoNext = CollectorWhatToDoNextAction.MoveToAZN;
                        else
                            this.m_WhatToDoNext = CollectorWhatToDoNextAction.MoveToHoshimi;
                    }
                }
            }
        }

        private void CollectActions()
        {
            switch (this.m_WhatToDoNext)
            {
                case CollectorWhatToDoNextAction.NothingToDo:
                    my_group = ((myPlayer)this.PlayerOwner).Groups[this.InternalName];
                    this.HP_point = my_group.location;

                    goto DirectAcces;
                //break;
                case CollectorWhatToDoNextAction.CollectAZN:
                    this.CollectFrom(this.Location, m_turns_of_recollection);
                    this.m_WhatToDoNext = CollectorWhatToDoNextAction.MoveToHoshimi;
                    break;

                case CollectorWhatToDoNextAction.MoveToHoshimi:
                    //this.MoveTo(Utils.getNearestPoint(this.Location, ((myPlayer)this.PlayerOwner).HoshimiEntities));
                    checkForStock();
                    this.MoveTo(HP_point);
                    this.m_WhatToDoNext = CollectorWhatToDoNextAction.TransferToNeedle;
                    break;

                case CollectorWhatToDoNextAction.TransferToNeedle:
                    this.TransferTo(this.Location, m_turns_of_recollection);
                    this.m_WhatToDoNext = CollectorWhatToDoNextAction.MoveToAZN;
                    break;

                case CollectorWhatToDoNextAction.MoveToAZN:
                DirectAcces:
                    this.MoveTo(Utils.getNearestPoint(this.HP_point, ((myPlayer)this.PlayerOwner).AZNEntities));
                    this.m_WhatToDoNext = CollectorWhatToDoNextAction.CollectAZN;
                    break;
            }
        }

        //TODO: Cambiar para que nos cambie de grupo
        private void checkForStock()
        {
            if (my_group.needle == null || !(my_group.needle.Stock < my_group.needle.ContainerCapacity))
            {
                Dictionary<String, Group> groups = ((myPlayer)this.PlayerOwner).Groups;
                List<Group> ex_groups = ((myPlayer)this.PlayerOwner).ExGroups;
                ex_groups.Add(my_group);
                my_group = Utils.getNearestEntity(this.Location, groups, ex_groups);
                HP_point = my_group.location;
            }
        }

        public void SetTurnsOffRecollection(int _turns)
        {
            this.m_turns_of_recollection = _turns;
        }

        public int GetTurnsOfRecollection()
        {
            return this.m_turns_of_recollection;
        }


        #endregion
    }    
    #endregion

    #region Needle
    [Characteristics(ContainerCapacity = 100, CollectTransfertSpeed = 0, Scan = 0, MaxDamage = 0, DefenseDistance = 0, Constitution = 50)]
    public class Needle : VG.Common.NanoNeedle, IActionable
    {
        public const int SquadNumber = 0;
        #region IAction Members

        public enum WhatToDoNextAction
        {
            NothingToDo,
            AutoDestroy,
            WaitingForAttackPoints,
            Idle,
        }
        private Group my_group = null;
        private WhatToDoNextAction m_WhatToDoNext = WhatToDoNextAction.NothingToDo;


        public void DoActions()
        {
            switch (m_WhatToDoNext)
            {
                case WhatToDoNextAction.NothingToDo:
                    my_group = ((myPlayer)this.PlayerOwner).Groups[this.InternalName];
                    my_group.needle = this;
                    m_WhatToDoNext = WhatToDoNextAction.WaitingForAttackPoints;
                    break;

                case WhatToDoNextAction.WaitingForAttackPoints:
                    foreach (NanoBotInfo bot in this.PlayerOwner.OtherNanoBotsInfo)
                    {
                        if (bot.PlayerID == 0)
                        {
                            if (Utils.SquareDistance(this.Location, bot.Location) <= this.DefenseDistance)
                            {
                                this.DefendTo(bot.Location, 4);
                            }
                        }
                    }
                    break;             
                
                case WhatToDoNextAction.AutoDestroy:
                    this.ForceAutoDestruction();
                    break;

                case WhatToDoNextAction.Idle:
                    break;
            }
            //TODO: meter codigo para detectar muertes
        }
        #endregion
    }    
    #endregion

    #region Explorer
    [Characteristics(ContainerCapacity = 0, CollectTransfertSpeed = 0, Scan = 30, MaxDamage = 0, DefenseDistance = 0, Constitution = 10)]
    public class Explorer : VG.Common.NanoExplorer, IActionable
    {
        public enum WhatToDoNextAction
        {
            WaitingForPoints,
            MoveToPoint,
            Attack,
            WaitingForAttackPoints,

        }
        public WhatToDoNextAction WhatToDoNext = WhatToDoNextAction.WaitingForPoints;
        private Queue<Point> m_PointsToVisit = new Queue<Point>();

        public Queue<Point> PointsToVisit
        {
            get { return m_PointsToVisit; }
        }

        public void DoActions()
        {
            switch (this.WhatToDoNext)
            {
                case WhatToDoNextAction.WaitingForPoints:
                    break;

                // exploracion.
                case WhatToDoNextAction.MoveToPoint:
                    MakeMove();
                    WhatToDoNext = WhatToDoNextAction.WaitingForAttackPoints;
                    break;
            }
        }

        private void MakeMove()
        {
            if (this.PointsToVisit.Count > 0)
                this.MoveTo(PointsToVisit.Dequeue());
            else
                this.ForceAutoDestruction();
        }


    }    
    #endregion
    
    #region Protector
    [Characteristics(ContainerCapacity = 0, CollectTransfertSpeed = 0, Scan = 5, MaxDamage = 5, DefenseDistance = 12, Constitution = 25)]
    public class Protector : VG.Common.NanoCollector, IActionable
    {
        private Queue<Point> m_PointsToAttack = new Queue<Point>();

        public enum WhatToDoNextAction
        {
            WaitingForAttackPoints,
            Attack,
            GoingToPointOfAtack,
        }

        public Queue<Point> PointsToAttack
        {
            get { return m_PointsToAttack; }
        }

        public WhatToDoNextAction WhatToDoNext = WhatToDoNextAction.WaitingForAttackPoints;

        private Point point; // point of attack.

        public void DoActions()
        {
            switch (this.WhatToDoNext)
            {
                case WhatToDoNextAction.WaitingForAttackPoints:
                    break;

                case WhatToDoNextAction.GoingToPointOfAtack:
                    point = PointsToAttack.Dequeue();
                    this.MoveTo(point);
                    break;

                // ataque.
                case WhatToDoNextAction.Attack:
                    AttackNextPoint();
                    WhatToDoNext = WhatToDoNextAction.WaitingForAttackPoints;
                    break;
            }
        }

        private void AttackNextPoint()
        {
            if (this.PointsToAttack.Count > 0)
                this.DefendTo(point, 4);
            else
                this.ForceAutoDestruction();
        }

    } 
    #endregion

    #region Defender
    [Characteristics(ContainerCapacity = 0, CollectTransfertSpeed = 0, Scan = 5, MaxDamage = 5, DefenseDistance = 12, Constitution = 25)]
    public class Defender : VG.Common.NanoCollector, IActionable
    {
        public enum WhatToDoNextAction
        {
            Nothing,
            WaitingForAttackPoints,
            Attack,
            GoingToPointOfAtack,
        }

        Point HP_point;
        Group my_group;

        public WhatToDoNextAction WhatToDoNext = WhatToDoNextAction.Nothing;

        //private Point point; // point of attack.

        public void DoActions()
        {
            if (this.State == NanoBotState.WaitingOrders)
                Actions();
            else if (this.State == NanoBotState.Moving)
            {
                foreach (NanoBotInfo bot in this.PlayerOwner.OtherNanoBotsInfo)
                {
                    if (bot.PlayerID == 0)
                    {                        
                        if (Utils.MDistance(this.Location, bot.Location) <= this.DefenseDistance + 3)
                        {                     
                            this.StopMoving();
                            this.DefendTo(bot.Location, 4);
                        }
                    }
                }
            }

        }

        private void Actions()
        {
            switch (this.WhatToDoNext)
            {
                case WhatToDoNextAction.Nothing:                    
                    this.my_group = ((myPlayer)this.PlayerOwner).Groups[this.InternalName];
                    this.HP_point = my_group.location;
                    this.MoveTo(HP_point);
                    WhatToDoNext = WhatToDoNextAction.WaitingForAttackPoints;
                    break;

                case WhatToDoNextAction.WaitingForAttackPoints:
                    foreach (NanoBotInfo bot in this.PlayerOwner.OtherNanoBotsInfo)
                    {
                        if (bot.PlayerID == 0)
                        {                            
                            if (Utils.MDistance(this.Location, bot.Location) <= this.DefenseDistance + 3)
                            {
                                this.DefendTo(bot.Location, 4);
                            }
                        }
                    }
                    break;
            }
        }
    }
    #endregion

    #region Scout
    [Characteristics(ContainerCapacity = 0, CollectTransfertSpeed = 0, Scan = 30, MaxDamage = 0, DefenseDistance = 0, Constitution = 10)]
    public class Scout : VG.Common.NanoExplorer, IActionable
    {
        public enum WhatToDoNextAction
        {
            Init,
            MoveToPoint,
        }
        public WhatToDoNextAction WhatToDoNext = WhatToDoNextAction.Init;
        
        public void DoActions()
        {
            if (this.State == NanoBotState.WaitingOrders)
            {
                this.MoveTo(this.PlayerOwner.AI.Location);
            }
        }        
    }
    #endregion

    #region Radar
    [Characteristics(ContainerCapacity = 0, CollectTransfertSpeed = 0, Scan = 30, MaxDamage = 0, DefenseDistance = 0, Constitution = 10)]
    public class Radar : VG.Common.NanoExplorer, IActionable
    {
        public enum WhatToDoNextAction
        {
            Init,
            Idle,
        }
        public WhatToDoNextAction m_WhatToDoNext = WhatToDoNextAction.Init;
        Point HP_point;
        Group my_group;

        public void DoActions()
        {
            if (this.State == NanoBotState.WaitingOrders)
            {
                switch (m_WhatToDoNext)
                {
                    case WhatToDoNextAction.Init:
                        this.my_group = ((myPlayer)this.PlayerOwner).Groups[this.InternalName];
                        this.HP_point = my_group.location;
                        this.MoveTo(HP_point);
                        m_WhatToDoNext = WhatToDoNextAction.Idle;
                        break;
                    case WhatToDoNextAction.Idle:
                        break;
                }                
            }
        }
    }
    #endregion

    #region Guard
    [Characteristics(ContainerCapacity = 0, CollectTransfertSpeed = 0, Scan = 0, MaxDamage = 5, DefenseDistance = 12, Constitution = 30)]
    public class Guard : VG.Common.NanoCollector, IActionable
    {
        public enum WhatToDoNextAction
        {
            Nothing,
            WaitingForAttackPoints,
            Attack,
            GoingToPointOfAtack,
        }

        public WhatToDoNextAction WhatToDoNext = WhatToDoNextAction.Nothing;

        //private Point point; // point of attack.

        public void DoActions()
        {
            if (this.State == NanoBotState.WaitingOrders)
                this.MoveTo(this.PlayerOwner.AI.Location);
            else if (this.State == NanoBotState.Moving)
            {
                foreach (NanoBotInfo bot in this.PlayerOwner.OtherNanoBotsInfo)
                {
                    if (bot.PlayerID == 0)
                    {
                        if (Utils.MDistance(this.Location, bot.Location) <= this.DefenseDistance + 2)
                        {
                            this.StopMoving();
                            this.DefendTo(bot.Location, 4);
                        }
                    }
                }
            }

        }        
    }
    #endregion
}
